var BaseControl = Class.create({
    name:null,
    view:null,
    selector:null,
    events:null,
    url:null,
    fresh:null,
    ajaxMethod:null,

    initialize: function(element)
    {
        this.ajaxMethod = 'get';
        this.events = new Hash();
        this.loadView(element);
    },

    loadView: function(element)
    {
        this.view = $(element);
        if (!this.view.control)
        {
            this.name = this.view.id;
            this.view.control = this;
            this.url = this.view.getAttribute('url');
            this.observeEvent();
            this.fresh = true;
        }
        else
        {
            this.fresh = false;
        }
    },

    observeEvent: function(){},

    observe: function(eventName, callback)
    {
        if (!this.events.get(eventName))
            this.events.set(eventName, new Array());
        var e = this.events.get(eventName);
        e.push(callback);
    },

    stopObserving: function()
    {
        this.events = new Hash();
    },

    fire: function(eventName, memo)
    {
        if (this.events.get(eventName))
            this.events.get(eventName).each(function(callback){
                callback(memo);
            });
    },

    up: function(selector)
    {
        return this.view.up(selector);
    },

    down: function(selector)
    {
        return this.view.down(selector);
    },

    update: function(value)
    {
        return this.view.update(value);
    },

    insert: function(e)
    {
        return this.view.insert(e);
    },

    serialize: function()
    {
        var elements = this.view.find('input', 'select', 'textarea');
        return Form.serializeElements(elements);
    },

    refresh: function()
    {
        this.ajax(this.serialize());
    },

    ajax: function(params)
    {
        if (!this.url) throw this.name+' url is empty';
        var me = this;
        var action = this.getAction();
        Client.ajax(this.url, {
            parameters: params,
            method: me.ajaxMethod,
            onComplete: function(response){
                var wrapper = me.up();
                wrapper.update(response);
                me.loadView(wrapper.down());
                me.fire('ajaxcomplete', {action: action});
                if (me.onAjaxComplete) me.onAjaxComplete(); // hack for grid select
            }
        });
    },

    observeHashChange: function()
    {
        var me = this;
        jQuery(this.view).hashchange(function(e, newHash){
            me.onHashChange(newHash);
        });
        jQuery.hash.init('blank.html');
    },

    onHashChange: function(newHash)
    {
    },

    getHash: function(key, hash)
    {
        var map = hash.toQueryParams(';', ':');
        return map[key] ? map[key] : '';
    },

    setHash: function(key, params)
    {
        var index = location.href.indexOf('#');
        var hash = (index == -1 ? '' : location.href.substr(index + 1));
        var map = hash.toQueryParams(';', ':');
        map[key] = params;
        jQuery.hash.go($H(map).toHashString());
    },

    request: function(callback)
    {
        Client.ajax(this.url, {
            parameters: this.serialize(),
            onComplete: callback
        });
    },

    getInput: function(key)
    {
        return this.findOne('input[name="'+key+'"]');
    },

    addInput: function(key)
    {
        var input = new Element('input', {'name':key, 'type':'hidden'});
        this.view.insert(input);
        return input;
    },

    setParam: function(key, value)
    {
        var input = this.getInput(key);
        if (!input) input = this.addInput(key);
        input.value = value;
        return this;
    },

    getParam: function(key)
    {
        var input = this.getInput(key);
        return input ? input.value : false;
    },

    processAction: function(action)
    {
        this.ajaxMethod = 'post';
        this.setAction(action).refresh();
        this.ajaxMethod = 'get';
    },

    setAction: function(value)
    {
        return this.setParam('action', value);
    },

    getAction: function()
    {
        return this.getParam('action');
    },

    find: function()
    {
        return Selector.findChildElements(this.view, $A(arguments));
    },

    findOne: function()
    {
        return Selector.findChildElements(this.view, $A(arguments)).first();
    }
});